home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / WAIS / ir / irretrvl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  8.5 KB  |  332 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4.   
  5. */
  6.  
  7.  
  8. /* retrieval part of the serial ir engine.  if you are using a different 
  9.    storage system for the documents, replace this file. */
  10.  
  11. #include "irretrvl.h"
  12. #include <string.h>
  13. #include "futil.h"
  14. #include <ctype.h>  /* for isspace */
  15.  
  16. /*----------------------------------------------------------------------*/
  17.  
  18.  
  19. static boolean parseDocID
  20.   _AP((DocObj* doc,char* filename,long* start_character,
  21.        long* end_character,long* errorCode));
  22.  
  23. static boolean
  24. parseDocID(doc,filename,start_character,end_character,errorCode)
  25. DocObj* doc;
  26. char* filename;
  27. long* start_character;
  28. long* end_character;
  29. long* errorCode;
  30. {
  31.   DocID* theDocID = NULL;
  32.   char* local_id = NULL;
  33.   char* token = NULL;
  34.   long i;
  35.  
  36.   theDocID = docIDFromAny(doc->DocumentID);
  37.  
  38.   local_id = anyToString(GetLocalID(theDocID));
  39.   
  40.   freeDocID(theDocID);
  41.  
  42.   /* parse the doc id into start pos, end pos, and filename */
  43.   /* first the start char */
  44.   token = local_id;
  45.   for (i = 0; local_id[i] != '\0' && isspace(local_id[i]) == false; i++)
  46.     ;
  47.   if (local_id[i] == '\0')
  48.    { 
  49.      waislog(WLOG_HIGH, WLOG_ERROR, 
  50.          "Attempt to retrieve data for bad doc-id: '%s'",local_id); 
  51.      *errorCode = GDT_BadDocID;
  52.      s_free(local_id);
  53.      return(false);
  54.    }
  55.   local_id[i] = '\0';
  56.   sscanf(token,"%ld",start_character);
  57.   /* now the second char */
  58.   token = local_id + i + 1;
  59.   for (++i; local_id[i] != '\0' && isspace(local_id[i]) == false; i++)
  60.    ;
  61.   if (local_id[i] == '\0')
  62.    { 
  63.      waislog(WLOG_HIGH, WLOG_ERROR, 
  64.          "attempt to retrieve data for bad doc-id: '%s'",
  65.          local_id);
  66.      *errorCode = GDT_BadDocID;
  67.      s_free(local_id);
  68.      return(false);
  69.    }
  70.   local_id[i] = '\0';
  71.   sscanf(token,"%ld",end_character);
  72.   /* and finally the file name */
  73.   strncpy(filename,local_id + i + 1,MAX_FILENAME_LEN);
  74.   s_free(local_id);
  75.   return(true);
  76. }
  77.  
  78.  
  79. /*----------------------------------------------------------------------*/
  80.  
  81. WAISDocumentText* getData(doc, databaseName, errorCode)
  82. DocObj* doc;
  83. char *databaseName;
  84. long* errorCode;
  85. /* it isn't text, so we can just grab data */
  86. {
  87.   FILE* file = NULL;
  88.   char fileName[MAX_FILENAME_LEN + 1];
  89.   WAISDocumentText* data = NULL;
  90.   long start,end;        /* position of the document in the file */
  91.   long startByte,endByte,bytes,bytesRead; /* part of the doc that we want */
  92.   char* buffer = NULL;
  93.   any* bufAny = NULL;
  94.  
  95.   /* we can only handle byte chunks here */
  96.   if ((doc->ChunkCode == CT_byte) ||
  97.       (doc->ChunkCode == CT_document)) {
  98.     if (parseDocID(doc,fileName,&start,&end,errorCode) == false)
  99.       return(NULL);
  100.  
  101.     file = s_fopen(fileName,"rb"); 
  102.     if (file == NULL)
  103.       { 
  104.     waislog(WLOG_HIGH, WLOG_ERROR, 
  105.         "attempt to retrieve data for missing doc-id: '%s'",
  106.         fileName);
  107.     *errorCode = GDT_MissingDocID;
  108.     return(NULL);
  109.       }
  110.  
  111.     if (doc->ChunkCode == CT_byte) {
  112.       startByte = doc->ChunkStart.Pos + start;
  113.       endByte = doc->ChunkEnd.Pos + start;
  114.     }
  115.     else {
  116.       startByte = start;
  117.       endByte = end;
  118.     }
  119.  
  120.     waislog(WLOG_LOW, WLOG_RETRIEVE,
  121.         "Retrieving DocID: %d %d %s, byte: %d %d, from database %s", 
  122.         start, end, fileName, startByte, endByte, databaseName);
  123.  
  124.     if (endByte > end && end != 0)
  125.       { 
  126.     waislog(WLOG_HIGH, WLOG_ERROR, 
  127.         "retrieval beyond bounds of document %ld in file <%s>",
  128.         endByte,fileName);
  129.     *errorCode = GDT_BadRange;
  130.     return(NULL);
  131.       }
  132.    
  133.     /* get the bytes */
  134.     if (fseek(file,startByte,SEEK_SET) != 0)
  135.       { 
  136.     waislog(WLOG_HIGH, WLOG_ERROR, 
  137.         "retrieval can't seek to %ld in file <%s>",startByte,
  138.         fileName);
  139.     *errorCode = GDT_BadRange;
  140.     return(NULL);
  141.       }
  142.  
  143.     bytes = endByte - startByte; 
  144.     buffer = (char*)s_malloc(bytes);
  145.   
  146.     bytesRead = fread((void*)buffer,(size_t)sizeof(char),bytes,file);
  147.   
  148.     if (bytesRead != bytes)
  149.       { 
  150.     waislog(WLOG_HIGH, WLOG_ERROR, 
  151.         "retrieval error in file <%s>",fileName);
  152.     *errorCode = GDT_BadRange;
  153.     return(NULL);
  154.       }
  155.   
  156.     bufAny = makeAny(bytesRead,buffer);
  157.   
  158.     data = makeWAISDocumentText(duplicateAny(doc->DocumentID),0L,bufAny);
  159.   
  160.     /* the any and the buffer are freed by freeWAISSearchResponse() */
  161.     s_fclose(file);
  162.   
  163.     *errorCode = GDT_NoError;
  164.   
  165.     return(data);
  166.   }
  167.   else
  168.     { 
  169.       waislog(WLOG_HIGH, WLOG_ERROR, 
  170.           "search engine can only use whole documents or byte offsets for data lookup");
  171.       *errorCode = GDT_UnsupportedChunkType;
  172.       return(NULL);
  173.     }
  174.  
  175. }
  176.  
  177. /*----------------------------------------------------------------------*/
  178.  
  179. #define BUFSZ    (size_t)5000
  180.  
  181. WAISDocumentText* getDocumentText(doc, databaseName, errorCode)
  182. DocObj* doc;
  183. char *databaseName;
  184. long* errorCode;
  185. /* find the text for doc, get the sub part if any, finally construct and
  186.    return a WAISDocumentText.  If it can not find the document 
  187.    (or some other error) it returns NULL and sets errorCode.
  188.  */
  189. {
  190.   WAISDocumentText* text = NULL;
  191.   FILE* file = NULL;
  192.   char* buffer = NULL;
  193.   any* bufAny = NULL;
  194.   char filename[MAX_FILENAME_LEN + 1];
  195.   long start_character;
  196.   long end_character;
  197.   register long i;
  198.   long bytes,bytesRead;
  199.   long startByte,endByte,byte,lines;
  200.   
  201.   /* we can only handle line chunks for now */
  202.   if (doc->ChunkCode != CT_line)
  203.    { 
  204.      waislog(WLOG_HIGH, WLOG_ERROR, 
  205.          "search engine can only use line offsets for now.");
  206.      
  207.      *errorCode = GDT_UnsupportedChunkType;
  208.      return(NULL);
  209.    }
  210.  
  211.   if (parseDocID(doc,filename,&start_character,&end_character,errorCode) == 
  212.       false)
  213.     return(NULL);
  214.  
  215.   waislog(WLOG_LOW, WLOG_RETRIEVE,
  216.       "Retrieving DocID: %d %d %s, line range: %d %d, from database %s", 
  217.       start_character, end_character, filename,
  218.       doc->ChunkStart.Pos, doc->ChunkEnd.Pos,
  219.       databaseName);
  220.   /* check the database */
  221.   if(NULL == databaseName){
  222.     *errorCode = GDT_MissingDatabase;
  223.     return(NULL);
  224.   }
  225.   
  226.  
  227.   file = s_fopen(filename,"r");
  228.   if (file == NULL)
  229.    { 
  230.      waislog(WLOG_HIGH, WLOG_ERROR, 
  231.          "attempt to retrieve text for bad doc-id: '%s'",
  232.          doc->DocumentID);
  233.      
  234.      *errorCode = GDT_MissingDocID;
  235.      return(NULL);
  236.    }
  237.  
  238.   if(0 != fseek(file, start_character, SEEK_SET))
  239.    { 
  240.      waislog(WLOG_HIGH, WLOG_ERROR, 
  241.          " error on attempt to seek into file");
  242.      
  243.      *errorCode = GDT_MissingDocID;
  244.      return(NULL);
  245.    }
  246.   /* find the start byte */
  247.   buffer = (char*)s_malloc(BUFSZ);
  248.   lines = byte = 0;
  249.   while (lines < doc->ChunkStart.Pos)
  250.    { /* search a buffer full */
  251.      bytesRead = fread(buffer,(size_t)sizeof(char),BUFSZ,file); 
  252.      for (i = 0; i < bytesRead && lines < doc->ChunkStart.Pos; i++, byte++)
  253.       { if (buffer[i] == '\n' || buffer[i] == '\r')
  254.       /* \r should not happen because we are reading the file in text 
  255.          mode */
  256.           lines++;
  257.       }
  258.      if (bytesRead == 0) /* cheasy handling files that don't end with nl */
  259.        lines++;
  260.    } 
  261.   startByte = byte;
  262.    
  263.   beFriendly();
  264.   
  265.   /* find the end byte */ /* this could be done while getting the bytes XXX */
  266.   /* search starting form the start pos */  
  267.   if (fseek(file,startByte + start_character,SEEK_SET) != 0) 
  268.    { 
  269.      waislog(WLOG_HIGH, WLOG_ERROR, 
  270.          "retrieval can't seek to %ld in file <%s>",
  271.          startByte,filename);
  272.      
  273.      *errorCode = GDT_BadRange;
  274.      return(NULL);
  275.    }
  276.  
  277.   beFriendly();
  278.   
  279.   while (lines < doc->ChunkEnd.Pos) 
  280.    { /* search a buffer full */
  281.      bytesRead = fread(buffer,(size_t)sizeof(char),BUFSZ,file); 
  282.      for (i = 0; i < bytesRead && lines < doc->ChunkEnd.Pos; i++, byte++)
  283.       { if (buffer[i] == '\n' || buffer[i] == '\r')
  284.       /* \r should not happen, we are reading the file in text mode */
  285.           lines++;
  286.       }
  287.      if (bytesRead == 0) /* cheasy handling of files that don't end with nl */
  288.        lines++;
  289.    } 
  290.   endByte = byte;
  291.    
  292.   beFriendly();
  293.   
  294.   s_free(buffer);
  295.      
  296.   /* get the bytes */
  297.   if (fseek(file,startByte + start_character,SEEK_SET) != 0)
  298.    { 
  299.      waislog(WLOG_HIGH, WLOG_ERROR, 
  300.          "retrieval can't seek to %ld in file <%s>",startByte,
  301.          filename);
  302.      
  303.      *errorCode = GDT_BadRange;
  304.      return(NULL);
  305.    }
  306.    
  307.   bytes = endByte - startByte; 
  308.   buffer = (char*)s_malloc(bytes);
  309.   
  310.   bytesRead = fread((void*)buffer,(size_t)sizeof(char),bytes,file);
  311.   
  312.   if (bytesRead != bytes)
  313.    { 
  314.      waislog(WLOG_HIGH, WLOG_ERROR, 
  315.          "retrieval error in file <%s>",filename);
  316.      
  317.      *errorCode = GDT_BadRange;
  318.      return(NULL);
  319.    }
  320.   
  321.   bufAny = makeAny(bytesRead,buffer);
  322.   
  323.   text = makeWAISDocumentText(duplicateAny(doc->DocumentID),0L,bufAny);
  324.   
  325.   /* the any and the buffer are freed by freeWAISSearchResponse() */
  326.   s_fclose(file);
  327.   
  328.   *errorCode = GDT_NoError;
  329.   
  330.   return(text);
  331. }
  332.